package io.github.echarts.model.geometry;

/**
 * 表示二维空间中的尺寸（宽度和高度）
 */
public class Dimension {
    
    /**
     * 宽度
     */
    private final double width;
    
    /**
     * 高度
     */
    private final double height;
    
    /**
     * 创建一个尺寸对象
     * 
     * @param width 宽度
     * @param height 高度
     */
    public Dimension(double width, double height) {
        // 尺寸不允许为负数
        this.width = Math.max(0, width);
        this.height = Math.max(0, height);
    }
    
    /**
     * 创建宽高相等的正方形尺寸
     * 
     * @param size 宽高值
     * @return 正方形尺寸对象
     */
    public static Dimension square(double size) {
        return new Dimension(size, size);
    }
    
    /**
     * 创建空尺寸（宽高均为0）
     * 
     * @return 空尺寸对象
     */
    public static Dimension empty() {
        return new Dimension(0, 0);
    }
    
    /**
     * 获取宽度
     * 
     * @return 宽度值
     */
    public double getWidth() {
        return width;
    }
    
    /**
     * 获取高度
     * 
     * @return 高度值
     */
    public double getHeight() {
        return height;
    }
    
    /**
     * 获取面积
     * 
     * @return 面积值
     */
    public double getArea() {
        return width * height;
    }
    
    /**
     * 判断此尺寸是否为空（宽或高为0）
     * 
     * @return 如果宽或高为0，则返回true，否则返回false
     */
    public boolean isEmpty() {
        return width <= 0 || height <= 0;
    }
    
    /**
     * 计算宽高比
     * 
     * @return 宽高比（宽/高），如果高度为0，则返回0
     */
    public double getAspectRatio() {
        return (height > 0) ? width / height : 0;
    }
    
    /**
     * 创建一个新的尺寸对象，表示按指定比例缩放后的尺寸
     * 
     * @param scale 缩放比例
     * @return 缩放后的尺寸对象
     */
    public Dimension scale(double scale) {
        return new Dimension(width * scale, height * scale);
    }
    
    /**
     * 创建一个新的尺寸对象，表示与另一个尺寸对象的和（宽与宽相加，高与高相加）
     * 
     * @param other 另一个尺寸对象
     * @return 尺寸和
     */
    public Dimension add(Dimension other) {
        return new Dimension(this.width + other.width, this.height + other.height);
    }
    
    /**
     * 创建一个新的尺寸对象，表示当前尺寸和指定宽高增量的和
     * 
     * @param deltaWidth 宽度增量
     * @param deltaHeight 高度增量
     * @return 调整后的新尺寸对象
     */
    public Dimension expand(double deltaWidth, double deltaHeight) {
        return new Dimension(this.width + deltaWidth, this.height + deltaHeight);
    }
    
    /**
     * 创建一个新的尺寸对象，表示当前尺寸在不改变宽高比的情况下，适应目标尺寸区域
     * 
     * @param targetWidth 目标宽度
     * @param targetHeight 目标高度
     * @param scaleUp 如果当前尺寸小于目标区域，是否允许放大
     * @return 调整后的新尺寸对象
     */
    public Dimension fitTo(double targetWidth, double targetHeight, boolean scaleUp) {
        if (width == 0 || height == 0) {
            return new Dimension(targetWidth, targetHeight);
        }
        
        double widthRatio = targetWidth / width;
        double heightRatio = targetHeight / height;
        
        // 选择较小的比例，保证适应目标区域
        double ratio = Math.min(widthRatio, heightRatio);
        
        // 如果不允许放大，且比例大于1，则保持原始尺寸
        if (!scaleUp && ratio > 1) {
            return this;
        }
        
        return new Dimension(width * ratio, height * ratio);
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        
        Dimension dimension = (Dimension) o;
        
        if (Double.compare(dimension.width, width) != 0) return false;
        return Double.compare(dimension.height, height) == 0;
    }
    
    @Override
    public int hashCode() {
        int result;
        long temp;
        temp = Double.doubleToLongBits(width);
        result = (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(height);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
    
    @Override
    public String toString() {
        return "Dimension{" +
                "width=" + width +
                ", height=" + height +
                '}';
    }
} 